import json
import datetime
import random

from app import dbop
from app import tools
from app import error
from app.rule import ChessGame


def load_match_game(match_id, seq=None):
    print("machine_move:", match_id)
    move_record = dbop.ChessGameProcessDAO.get_record_by_filter_key({
        "match_id": match_id,
        "seq": seq
    })

    # last_move = dbop.ChessGameProcessDAO.get_match_last_record(match_id)
    if move_record is None:
        game = ChessGame()
    else:
        data_json = tools.safe_json_loads(move_record.status)
        kill_game = data_json.get('kill_game')
        if kill_game:
            return
        game = ChessGame(data_json)
    return game


def machine_move_select(game):
    cur_player = game.cur_player
    # opt_move = game.get_player_opt_move(cur_player)
    game_analysis = game.get_piece_attack()
    opt_move = game_analysis.get('opt_move')

    # print("opt_move:", opt_move)
    move_score_info = {}
    analysis_data = {}

    #
    for item in opt_move:
        # print(item)
        move, piece = item[:]
        target_piece = game.change_status_raw(move)

        # 检查对将的情况。
        game.build_piece_index()
        w_same_road = game.check_w_same_road()
        # print("check_w_same_road:", w_same_road)
        # 对将， 需要复原。
        if w_same_road:
            game.rewind_status_raw(move, target_piece)
            continue

        # 检查是否有将军的情况
        result = game.get_piece_attack()
        # print('attack info:', result)
        attack_info_backward = result.get('attack_info_backward').get(game.cur_player)

        # w_attacked = game.check_w_attacked(game.cur_player)
        w_attacked = (game.cur_player + 'W') in attack_info_backward
        # print("w_attacked:", w_attacked)
        if w_attacked:
            game.rewind_status_raw(move, target_piece)
            continue

        # 以下是允许的走法。
        score = result.get("score_diff").get(cur_player)
        move_score = 0
        if target_piece:
            move_score = game.piece_weight.get(target_piece[1])

        print("move score:", item, score, move_score, score + 2*move_score)
        detail_info = {
            'attack_info': result.get('attack_info'),
            'attack_info_backward': result.get('attack_info_backward'),
            'attack_score': result.get('attack_score'),
            'attack_score_backward': result.get('attack_score_backward'),
        }
        print("     detail info:", json.dumps(detail_info))
        # print(result.get("attack_info"), ",", result.get("attack_info_backward"),
        #       ",", result.get("attack_score"), ",", result.get("attack_score_backward"),
        #       ",", result.get("score_diff"))

        # print(result.get("attack_info"), ",", result.get("attack_info_backward"), ",", result.get("score_diff"))
        total_score = score + 2*move_score
        if total_score not in move_score_info:
            move_score_info[total_score] = []
        move_score_info[total_score].append(item)

        # 需要计算每一步走棋后， 棋盘局面的优势分。 怎么计算优势分。
        game.rewind_status_raw(move, target_piece)

        # 记录每一步走法的分析结果。
        opt_move_key = json.dumps(item)
        analysis_data[opt_move_key] = result

    # 查找最大得分的走法
    max_score = sorted(move_score_info.keys())[-1]
    max_score_move = move_score_info[max_score]
    select_move = random.choice(max_score_move)
    # print("select_move:", max_score_move, select_move)
    # 正式走棋
    return select_move[0], analysis_data, move_score_info

    #
    # game.print_status()


def cal_machine_move(game):
    pass


def cal_machine_move_rand(game, player):
    opt_move = game.get_player_opt_move(player)
    print("opt_move:", opt_move)

    for _ in range(100):
        rand_move = random.choice(opt_move)
        print("select move:", rand_move)
        move = rand_move[0]
        res = game.step_check(move)
        if 'OK' != res:
            return {
                "error": error.E_PARAM_WRONG,
                'err_msg': res
            }
        target_piece = game.change_status_raw(move)

        # 下面这个函数是否放在 change_status_raw 里面比较好。
        game.build_piece_index()
        w_same_road = game.check_w_same_road()
        print("check_w_same_road:", w_same_road)
        # 对将， 需要复原。
        if w_same_road:
            game.rewind_status_raw(move, target_piece)
            continue

        # 检查是否有将军的情况
        result = game.get_piece_attack()
        print('attack info:', result)
        attack_info_backward = result.get('attack_info_backward').get(game.cur_player)

        # w_attacked = game.check_w_attacked(game.cur_player)
        w_attacked = (game.cur_player + 'W') in attack_info_backward
        print("w_attacked:", w_attacked)
        if w_attacked:
            game.rewind_status_raw(move, target_piece)
            continue
        #
        game.rewind_status_raw(move, target_piece)
        return move


def machine_move(match_id, player):
    print("machine_move:", match_id, player)
    last_move = dbop.ChessGameProcessDAO.get_match_last_record(match_id)
    if last_move is None:
        game = ChessGame()
    else:
        data_json = tools.safe_json_loads(last_move.status)
        kill_game = data_json.get('kill_game')
        if kill_game:
            return
        game = ChessGame(data_json)

    # opt_move = game.get_player_opt_move(player)
    # print("opt_move:", opt_move)
    #
    # for _ in range(100):
    #     rand_move = random.choice(opt_move)
    #     print("select move:", rand_move)
    #     move = rand_move[0]
    #     res = game.step_check(move)
    #     if 'OK' != res:
    #         return {
    #             "error": error.E_PARAM_WRONG,
    #             'err_msg': res
    #         }
    #     target_piece = game.change_status_raw(move)
    #
    #     # 下面这个函数是否放在 change_status_raw 里面比较好。
    #     game.build_piece_index()
    #     w_same_road = game.check_w_same_road()
    #     print("check_w_same_road:", w_same_road)
    #     # 对将， 需要复原。
    #     if w_same_road:
    #         game.rewind_status_raw(move, target_piece)
    #         continue
    #
    #     # 检查是否有将军的情况
    #     result = game.get_piece_attack()
    #     print('attack info:', result)
    #     attack_info_backward = result.get('attack_info_backward').get(game.cur_player)
    #
    #     # w_attacked = game.check_w_attacked(game.cur_player)
    #     w_attacked = (game.cur_player + 'W') in attack_info_backward
    #     print("w_attacked:", w_attacked)
    #     if w_attacked:
    #         game.rewind_status_raw(move, target_piece)
    #         continue

    # move = cal_machine_move_rand(game, player)
    if False:
        move = machine_move_select(game)[0]
    elif True:
        res = game.get_min_max_move(game.cur_player)
        print("res:", res)
        move = res[1][0][0]

    #
    target_piece = game.change_status_raw(move)
    game.build_piece_index()
    result = game.get_piece_attack()
    #
    game.switch_player()

    data = game.get_bord_status()

    # 已经切换了执棋方
    attack_info_backward = result.get('attack_info_backward').get(game.cur_player)
    w_attacked = (game.cur_player + 'W') in attack_info_backward
    # 只有将军了才去检查是否杀死了比赛
    if w_attacked:
        # 检查有没有杀死比赛
        kill_game = game.check_kill_game()
        # game.print_status()

        data['attack_w'] = True
        data['kill_game'] = kill_game
    else:
        data['attack_w'] = False
        data['kill_game'] = False
    data['attack_info_backward'] = result.get('attack_info_backward')
    print('data:', data)

    # 保存记录
    params = dict({
        'match_id': match_id,
        'seq': data.get('count')
    })
    params['move'] = json.dumps(move)
    params['dead_piece'] = target_piece
    params['status'] = json.dumps(data)
    params['update_time'] = datetime.datetime.now()

    dbop.ChessGameProcessDAO.update_record(None, params)


def test_module(params):
    match_id = params.get('match_id')
    seq = params.get('seq')
    game = load_match_game(match_id, seq)
    if False:
        res = machine_move_select(game)
        print("select move:", res[0], res[2])
    elif True:
        print("test_module.1")
        res = game.get_min_max_move(game.cur_player)
    else:
        res = game.get_player_opt_move_v2(game.cur_player)

    return res


